package com.nicolasprof.profgallery.navigation.scrollbar {
	import com.nicolasprof.profgallery.assets.ScrollbarBackground;
	import com.nicolasprof.profgallery.assets.ScrollbarBar;

	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	/**
	 * @author Nicolas Prof
	 */
	public class ScrollBar extends Sprite {

		protected var _bg : ScrollbarBackground;
		protected var _bar : ScrollbarBar;
		protected var _ratio : Number;
		protected var _height : Number;
		protected var _isEnabled : Boolean;

		//DIRECTION
		public static const TOP : String = "top";
		public static const BOTTOM : String = "bottom";
		
		//Style
		protected const DISABLE_ALPHA : Number = 0.4;
		
		
		public function ScrollBar() {
		}
		private function calcRatio() : void {
			_ratio = _bar.y / (_height - _bar.height);
		}
		public function initiate($height : Number, $barRatio: Number = 0.2, $ratio: Number = 0) : void {		
			_ratio = $ratio;
			_bg = new ScrollbarBackground();
			_bar = new ScrollbarBar();
			_isEnabled = true;
			
			//DISPLAY LIST
			addChild(_bg);
			addChild(_bar);
			
			//LISTENERS
			_bar.addEventListener(MouseEvent.MOUSE_DOWN, onDown, false, 0, true);
			_bg.addEventListener(MouseEvent.MOUSE_DOWN, onBackgroundDown, false, 0, true);
			
			//ACTIONS
			_height = $height;
			
			_bar.height = _height * $barRatio;
			_bar.buttonMode = true;
			_bar.tabEnabled = false;
			
			_bg.height = _height;
			_bg.buttonMode = true;
			_bg.tabEnabled = false;
			
			
			setPos(ratio);
		}
		private function moveTo(direction : String) : void {
			var step: Number = (_height - _bar.height) * 0.05;
			switch(direction){
				case TOP :
					_bar.y -= step;
					if(_bar.y < 0) _bar.y = 0; 
					break;
				case BOTTOM :
					_bar.y += step;
					if(_bar.y > (_height - _bar.height)) _bar.y = (_height - _bar.height); 
					break;
				
			}
			calcRatio();
		}
		public function setPos(ratio : Number) : void {
			if(ratio > 1) return;
			_bar.y = (_height - _bar.height) * ratio;
			_ratio = ratio;
		}	
		public function update(ratio: Number = 0) : void {		
			setPos(ratio);
		}	
		public function updateBar($ratio : Number) : void {
			_bar.height = _height * $ratio;
			setPos(_ratio);
		}
		public function wheel(delta:int) : void {
			//TODO Use delta value
			if(!_isEnabled) return;
			if(delta < 0){
				moveTo(BOTTOM);
			}else{
				moveTo(TOP);
			}
			var sbe : ScrollBarEvent = new ScrollBarEvent(ScrollBarEvent.CHANGE);
			sbe.ratio = _ratio;
			dispatchEvent(sbe);
		}

		/**
		 * EVENTS
		 */
		private function onBackgroundDown(e : MouseEvent) : void {
			if(!_isEnabled) return;
			if(e.localY >= (_height - _bar.height)){
				_bar.y = (_height - _bar.height);
			}else {
				_bar.y = e.localY;
			}
			
			calcRatio();
			
			var sbe : ScrollBarEvent = new ScrollBarEvent(ScrollBarEvent.CHANGE);
			sbe.ratio = _ratio;
			dispatchEvent(sbe);
		}
		private function onDown(e : MouseEvent) : void {
			if(!_isEnabled) return;
			_bar.startDrag(false, new Rectangle(0, 0, 0, (_height - _bar.height)));
			
			_bar.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove, false, 0, true);
			_bar.stage.addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
		}
		
		private function onMove(e : MouseEvent) : void {
			calcRatio();
			
			var sbe : ScrollBarEvent = new ScrollBarEvent(ScrollBarEvent.MOVE);
			sbe.ratio = _ratio;
			dispatchEvent(sbe);
		}

		private function onUp(e : MouseEvent) : void {
			_bar.stopDrag();
			
			_bar.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
			_bar.stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
			
			var sbe : ScrollBarEvent = new ScrollBarEvent(ScrollBarEvent.CHANGE);
			sbe.ratio = _ratio;
			dispatchEvent(sbe);	
		}
		/**
		 * GETTERS AND SETTERS
		 */
		public function get enabled() : Boolean {
			return _isEnabled;
		}
		public function set enabled(state : Boolean) : void {
			_isEnabled = state;
			if(state){
				_bg.alpha = 1;
			}else{
				_bg.alpha = DISABLE_ALPHA;
			}
			_bar.visible = state;
			_bg.buttonMode = state;
		}
		public function get ratio() : Number {
			return _ratio;
		}
	}
}
